SternBrocotTree.ts ➔ rationalApproximation   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 23
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 18
dl 0
loc 23
ccs 16
cts 16
cp 1
crap 4
rs 9.5
c 0
b 0
f 0
1 5
import { MAX_LOOPS } from './config'
2 5
import Rat from './Rat'
3
4
/**
5
 * Find the rational number that best approximates the floating point number.
6
 */
7 5
export function rationalApproximation(n: number): Rat {
8 8
  let m0 = 1n,
9 8
    m1 = 0n,
10 8
    m2 = 0n,
11 8
    m3 = 1n
12 8
  const r = new Rat(1n)
13 8
  for (let i = 0; i < MAX_LOOPS; i++) {
14 1485
    if (r.approximates(n)) break
15 1478
    if (+r > n) {
16 51
      m0 += m1
17 51
      m2 += m3
18
    } else {
19 1427
      m1 += m0
20 1427
      m3 += m2
21
    }
22 1478
    r.n = m0 + m1
23 1478
    r.d = m2 + m3
24
  }
25 8
  return r
26
}
27
28
/**
29
 * Yield false for each left and true for each right.
30
 */
31 5
export function* pathToValue(n: number): Generator<boolean> {
32 15
  let m0 = 1n,
33 15
    m1 = 0n,
34 15
    m2 = 0n,
35 15
    m3 = 1n
36 15
  const r = new Rat(1n)
37 15
  for (let i = 0; i < MAX_LOOPS; i++) {
38 565
    if (r.approximates(n)) break
39 550
    const direction = n > +r
40 550
    yield direction
41 550
    if (!direction) {
42 112
      m0 += m1
43 112
      m2 += m3
44
    } else {
45 438
      m1 += m0
46 438
      m3 += m2
47
    }
48 550
    r.n = m0 + m1
49 550
    r.d = m2 + m3
50
  }
51
}
52
53
/**
54
 * Yield the values of the continued fraction, ie. the length of runs left/right.
55
 */
56 5
export function* continuedFraction(n: number): Generator<number> {
57 13
  let last = true
58 13
  let run = 0
59 13
  for (const direction of pathToValue(n)) {
60 546
    if (direction === last) {
61 441
      run++
62
    } else {
63 105
      yield run
64 105
      run = 1
65 105
      last = direction
66
    }
67
  }
68 13
  yield run + 1
69
}
70